<?php
namespace app\common\model\users;

use think\Model;
use think\Db;

/*************************************************  
*ClassName:     UserAccess
*Description:   用户访问模型
*Others:        
*************************************************/
class UsersAccess extends Model
{
    /**
     * Function:      createAccess
     * Description:   新建一个访问
     * （uid不存在就新建，存在就更新旧的access记录，与是否过期无关）
     * @author guoyu
     * @param string $uid                          用户id
     * @param string $expire                       过期时间
     * @Return array [error_code, error_msg, data => [uid, access_token, create_time, expire_time]]  用户访问凭据信息
     */
    static public function createAccess($uid = "", $expire = 7200)
    {
        self::clearExpire(); //清除所有过期access
        $result = ['error_code' => 0, 'error_msg' => ""];     
        $result_data = ['uid' => $uid];         
        $db_info = self::where('uid', $uid)->find();       
        if (empty($db_info['uid'])) {
            $access_token = md5(uniqid(rand()));
            $create_time = time();
            $expire_time = $create_time + $expire;
            $ip = isset($_SERVER["REMOTE_ADDR"]) ? $_SERVER["REMOTE_ADDR"] : 0;
            $data = ['uid' => $uid, 'access_token' => $access_token, 'create_time' => $create_time, 'expire_time' => $expire_time, 'ip' => $ip ];
            if (!self::create($data)) {
                return ['error_code' => 1, 'error_msg' => "创建access_token失败"];
            } else {
                $result_data['access_token'] = $data['access_token'];
                $result_data['create_time'] = $create_time;
                $result_data['expire_time'] = $expire_time;
            }
        } else {
            $access_token = $result_data['access_token'] = $db_info['access_token'];
            $result_data['create_time'] = $db_info['create_time'];
            $expire_time = time() + $expire;           
            if (self::where('access_token', $access_token)->update(['expire_time' => $expire_time])) {
                $result_data['expire_time'] = $db_info['expire_time'];
            } else {
                //return ['error_code' => 1, 'error_msg' => "更新access_token失败"];
            }
        }  
        $result['data'] = $result_data;
        return $result;
    }

    /** 
     * Function:      getAccess
     * Description:   获取access信息
     * @author  karl guoyu
     * @param   string $access_token                用户id
     * @return  array [error_code, error_msg, data] 用户访问凭据信息
     * 
     */    
    static public function getAccess($access_token)
    {
        $result = ['error_code' => 0, 'error_msg' => ""];
        $row = self::get(['access_token' => $access_token]);
        if (empty($row)){
            $result['error_code'] = 1;
            $result['error_msg'] = '会话不存在';
            return $result;
        }
        if ($row['expire_time'] < time()){
            $result['error_code'] = 2;
            $result['error_msg'] = '会话过期';
        } else {
            $result['data'] = $row->data;
        }
        return $result;
    }
    /**
     * getAccessValue 得到会话值
     * 只取会话中的value,并将value从json字符串变成数组；要判断会话是否过期
     * @karl guoyu
     * @DateTime 2016-12-27T23:47:29+0800
     * @param    string                   $access_token 
     * @return   array                    [error_code, error_msg, data]
     */
    static public function getAccessValue($access_token)
    {
        $result = ['error_code' => 0, 'error_msg' => ""];
        $row = self::where('access_token', $access_token)->find();
        if (empty($row) || time() > $row['expire_time']){
            $result['error_code'] = 1;
            $result['error_msg'] = '会话不存在或已过期';
        } else {
            $result['data'] = json_decode($row['value'],true);
        }
        return $result; 
    }

    /**
     * getAccessByUid 通过uid得到会话
     * @karl
     * @DateTime 2017-02-21T10:08:17+0800
     * @param    int                   $uid 用户id
     * @return   array                    [error_code, error_msg, data]
     */
    static public function getAccessByUid($uid)
    {   
        $result = ['error_code' => 0, 'error_msg' => ""];
        $row = self::where('uid', $uid)->find();
        if ($row){
            $result['error_code'] = 0;
            $result['error_msg'] = '';
            $result['data'] = $row;
        } else {
            $result['error_code'] = 1;
            $result['error_msg'] = '没有找到access_token';
        }
        return $result;
    }

    /**
     * saveAccessValue 写入会话值
     * 将$data数组变成json字符串存入value字段；与原数组合并；要判断会话是否过期
     * @karl guoyu
     * @DateTime 2016-12-27T23:47:29+0800
     * @param    string                   $access_token 
     * @param                             $data
     * @return   array                    [error_code, error_msg, data]
     */    
    static public function saveAccessValue($access_token, $data, $add_expire_time = 1)
    {
        $result = ['error_code' => 0, 'error_msg' => ""];
        $row = self::where('access_token', $access_token)->find();
        if (empty($row) || time() > $row['expire_time']){
            $result['error_code'] = 1;
            $result['error_msg'] = '此会话不存在或已过期';
            return $result;
        }
        if (empty($row['value'])) {
            $current_array = $data;
        } else {
            $current_array = array_replace(json_decode($row['value'], true), $data);
        }
        $current_json = json_encode($current_array);
        $new_expire_time = $row['expire_time'] + $add_expire_time;
        if (self::where('access_token', $access_token)->update(['expire_time' => $new_expire_time, 'value' => $current_json])) {
            $result['error_code'] = 0;
            $result['error_msg'] = '';
            $result['data'] = $current_array;
        } else {
            $result['error_code'] = 2;
            $result['error_msg'] = '写入会话值失败';
        }
        return $result;
    }

    /**
     * renew 续约 (算法还需修改)
     * @author guoyu
     * @param string   $access_token            用户id
     * @param integer   $expire_time            续约时间
     * @return array [error_code, error_msg, expire_time]  用户访问凭据信息
     */
    static public function renew($access_token, $expire_time = 20)
    {
        $result = ['error_code' => 0, 'error_msg' => ""];
        $row = self::where('access_token', $access_token)->find();
        if (empty($row)){
            $result['error_code'] = 1;
            $result['error_msg'] = '会话不存在';
            return $result;
        }
        //如果到期时间距离现在大于20s，则不允许续约
        if ($row['expire_time'] - time() < 20){
            $new_expire_time = time() + $expire_time;
            if (self::where('access_token', $access_token)->update(['expire_time' => $new_expire_time])) {
                $result['expire_time'] = $new_expire_time;
            }
        }
        return $result;
    }
    /**
     * deleteAccess 删除access
     * @author      karl guoyu
     * @DateTime   2016-12-28T01:07:26+0800
     * @param       string                   $access_token
     * @return      array                    [error_code, error_msg]
     */
    static public function deleteAccess($access_token)
    {
        $result = ['error_code' => 0, 'error_msg' => ""];
        $row = self::where('access_token', $access_token)->find();
        if (empty($row)){
            $result['error_code'] = 1;
            $result['error_msg'] = '该access_token不存在';
            return $result;
        }
        //在删除会话前记录下本次登陆时间在users里
        if (!self::where('access_token', '=', $access_token)->delete()) {
            $result['error_code'] = 2;
            $result['error_msg'] = '删除失败';
        }
        return $result;
    }
    /**
     * clearExpire 清除所有过期access
     * @karl guoyu
     * @DateTime 2016-12-28T01:07:26+0800
     * @return   array                    [error_code, error_msg]
     */
    static public function clearExpire()
    {
        $result = ['error_code' => 0, 'error_msg' => ""];
        $rows = self::where('expire_time','<',time())->select();
        if (empty($rows)) {
            $result['error_code'] = 0;
            $result['error_msg'] = '没有过期的access';
            return $result;
        }
        if (self::where('expire_time','<',time())->delete() ) {
            $result['error_code'] = 0;
            $result['error_msg'] = '';
        } else {
            $result['error_code'] = 1;
            $result['error_msg'] = '清除失败';
        }
        return $result;
    }

    /**
     * checkAccessToken 检查access_token
     * $uid与$access_token匹配 
     * @karl
     * @DateTime 2017-04-20T16:40:00+0800
     * @param    int                   $uid          用户id
     * @param    string                $access_token 
     * @return   array                 [error_code, error_msg]
     */
    static public function checkAccessToken($uid, $access_token)
    {
        $where['uid'] = $uid;
        $where['access_token'] = $access_token;
        $rows = self::where($where)->select();    
        if (empty($row)){
            $result['error_code'] = 1;
            $result['error_msg'] = '会话不存在';
            return $result;
        }
        if ($row['expire_time'] < time()){
            $result['error_code'] = 2;
            $result['error_msg'] = '会话过期';
        } else {
            $result['data'] = $row->data;
        }
        return $result;
    }
}
?>